﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace LFractal
{
	/// <summary>
	/// Interaction logic for LEntityRenderer.xaml
	/// </summary>
	public partial class LEntityRenderer : Window
	{
        private string sFileName = "";
        private LFractalLib.Entity entity = null;
        private WaitMessage waitScreen = new WaitMessage();
        private int currentLevel = 0;
        private double x0 = 0, y0 = 0;
        private double armLength = 30;
        private double alpha = 90.0;
        private double delta = 90.0;

        public int CurrentLevel
        {
            get { return currentLevel; }
            set { currentLevel = value; }
        }

        LFractalMainWindow parentWindow = null;
        LEntityEditor entityEditor = null;

		public LEntityRenderer(LFractalLib.Entity E, LEntityEditor editor, LFractalMainWindow p)
		{
            parentWindow = p;
            entityEditor = editor;
			this.InitializeComponent();
            waitScreen.Visibility = Visibility.Hidden;
            waitScreen.Topmost = true;
            waitScreen.WindowStartupLocation = WindowStartupLocation.CenterOwner;

			// Insert code required on object creation below this point.
            this.Loaded += new RoutedEventHandler(LEntityRenderer_Loaded);
            this.Closing += new System.ComponentModel.CancelEventHandler(LEntityRenderer_Closing);
            this.entity = E;
            this.entity.RenderStart += new LFractalLib.Entity.RenderStartHandler(entity_RenderStart);
            this.entity.RenderEnd += new LFractalLib.Entity.RenderEndHandler(entity_RenderEnd);
            this.entity.RenderLineToCanvas += new LFractalLib.Entity.LineDrawHandler(entity_RenderLineToCanvas);
		}

        void LEntityRenderer_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            parentWindow = null;
            entityEditor = null;
            waitScreen.Close();
        }

        void LEntityRenderer_Loaded(object sender, RoutedEventArgs e)
        {
            
        }

        void SetUIFromCurrentState()
        {
            txtLevel.Text = currentLevel.ToString();
            txtOrigin.Text = string.Format("{0},{1}", x0, y0);
            txtSegLenth.Text = armLength.ToString();
            txtAlpha.Text = alpha.ToString();
            txtDelta.Text = delta.ToString();
       }

        void entity_RenderLineToCanvas(double x1, double y1, double x2, double y2)
        {
            Line oLine = new Line();
            oLine.X1 = x1; oLine.Y1 = y1; oLine.X2 = x2; oLine.Y2 = y2;
            oLine.Stroke = Brushes.Black;
            oLine.StrokeThickness = 1.0d;
            drawingCanvas.Children.Add(oLine);
        }

        void entity_RenderEnd(LFractalLib.Entity E)
        {
            waitScreen.Hide();
        }

        void entity_RenderStart(LFractalLib.Entity E)
        {
            drawingCanvas.Children.Clear(); // clear canvas for new rendering
            drawingCanvas.UpdateLayout();
            waitScreen.Show();
        }

		private void LEntityRendererWindow_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			this.DragMove();
		}

		private void btnPrevLevel_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			int level = int.Parse( txtLevel.Text );
			if(level > 0)
			{
				level--;
				txtLevel.Text = string.Format("{0}", level);
                if (entity.ArmScalingFactor > 0)
                {
                    armLength *= entity.ArmScalingFactor;
                }
                else
                {
                    armLength /= - entity.ArmScalingFactor;
                }
                txtSegLenth.Text = armLength.ToString();
                UpdateStateAndRefresh();
			}
		}

		private void btnNextLevel_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			int level = int.Parse( txtLevel.Text );
			level++;
			txtLevel.Text = string.Format("{0}", level);
            currentLevel = level;
            armLength *= 0.75;
            txtSegLenth.Text = armLength.ToString();
            UpdateStateAndRefresh();
		}

		private void txtLevel_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
		{
			if(e.Key == Key.Up || e.Key == Key.PageUp)
			{
				btnNextLevel_Click(null, null);
			} else
				if(e.Key == Key.Down)
				{
					btnPrevLevel_Click(null, null);	
				} else
					if(e.Key == Key.Enter)
					{
                        UpdateStateAndRefresh();
					}
		}

		private void btnBack_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			this.Close();
		}

        public void DrawEntity()
        {
            if (entity != null)
            {
                this.x0 = this.ActualWidth * entity.X0;
                this.y0 = this.ActualHeight * entity.Y0;
                this.armLength = entity.ArmLength;
                this.alpha = entity.Alpha;
                this.delta = entity.Delta;

                SetUIFromCurrentState();
                RefreshDrawing();
            }
        }

        public void UpdateStateAndRefresh()
        {
            currentLevel = int.Parse(txtLevel.Text);
            string[] arrOrg = txtOrigin.Text.Split(",".ToCharArray());
            x0 = double.Parse(arrOrg[0].Trim());
            y0 = double.Parse(arrOrg[1].Trim());
            armLength = double.Parse(txtSegLenth.Text);
            alpha = double.Parse(txtAlpha.Text);
            delta = double.Parse(txtDelta.Text);

            RefreshDrawing();
        }

        public void RefreshDrawing()
        {
            if (entity != null)
            {
                entity.DrawViaDelegate(x0, y0, armLength, alpha, delta, currentLevel);
            }
        }

        private void btnRefresh_Click(object sender, RoutedEventArgs e)
        {
            UpdateStateAndRefresh();
        }

        private void txtAlpha_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                UpdateStateAndRefresh();
            }
        }

        private void txtDelta_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                UpdateStateAndRefresh();
            }
        }

        private void txtSegLenth_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                UpdateStateAndRefresh();
            }
        }

        private void txtOrigin_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                UpdateStateAndRefresh();
            }
        }

        private void menuSave_Click(object sender, RoutedEventArgs e)
        {
            if (sFileName.Length == 0)
            {
                int iCounter = 1;
                string sFolder = LFractalMainWindow.StorageFolder, sPath = string.Format("{0}{1}.xml", sFolder, entity.Name);
                while (System.IO.File.Exists(sPath))
                {
                    iCounter++;
                    sPath = string.Format("{0}{1}{2}.xml", sFolder, entity.Name, iCounter);
                }

                sFileName = sPath;
                System.IO.File.WriteAllText(sFileName, entity.ToXML());
                if (parentWindow != null) parentWindow.RefreshMyWorkList(LFractalMainWindow.StorageFolder);
            }
            else
            {
                System.IO.File.WriteAllText(sFileName, entity.ToXML());
            }
        }

        private void menuExportImage_Click(object sender, RoutedEventArgs e)
        {

        }

        private void menuShare_Click(object sender, RoutedEventArgs e)
        {

        }
	}
}